package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/go_module_two/metrics"
	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/thinkeridea/go-extend/exnet"
	yaml "gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
	"math/rand"
	_ "math/rand"
	"net"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"strconv"
	"strings"
	"time"
)

type Set struct {
	Log Log
}

type Log struct {
	V int `yaml:"v"`
}

var Setting = Set{}

func init() {
	file, err := ioutil.ReadFile("./conf/app.yaml")
	if err != nil {
		log.Fatal("fail to read file:", err)
	}
	err = yaml.Unmarshal(file, &Setting)
	if err != nil {
		log.Fatal("fail to yaml unmarshal:", err)
	}

}
func ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	statusOK := http.StatusOK
	err := r.Header.Get("err")
	if err != "" {
		statusOK = http.StatusForbidden
	}
	ok := strconv.Itoa(statusOK)
	fmt.Printf("ip=%s,statusCode=%s \n", RemoteIp(r), ok)
	glog.V(4).Info(fmt.Sprintf("ip=%s,statusCode=%s \n", RemoteIp(r), ok))
	header := r.Header
	for k, v := range header {
		w.Header().Add(k, strings.Join(v, ";"))
	}
	marshal, _ := json.Marshal(header)
	fmt.Printf("header=%s \n", string(marshal))
	glog.V(4).Info(string(marshal))

	w.WriteHeader(statusOK)
	m := make(map[string]string, 3)

	m["code"] = ok
	m["data"] = "dddd"
	m["go_version"] = runtime.Version()
	w.Header().Add("VERSION", os.Getenv("VERSION"))
	mjson, _ := json.Marshal(m)
	glog.V(2).Info(string(mjson))
	w.Write([]byte(string(mjson)))
}
func healthz(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.Write([]byte("{}"))
}

func randInt(min int, max int) int {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	return min + r.Intn(max-min)
}

func hello(w http.ResponseWriter, r *http.Request) {
	timer := metrics.NewTimer()
	defer timer.ObserveTotal()
	d := randInt(10, 2000)
	time.Sleep(time.Duration(d) * time.Millisecond)
	w.Header().Set("Content-Type", "application/json")
	w.Write([]byte("{}"))
}
func main() {
	metrics.Register()
	fmt.Printf("v=%s", strconv.Itoa(Setting.Log.V))
	flag.Set("v", strconv.Itoa(Setting.Log.V))
	glog.Info("start----")
	http.HandleFunc("/healthz", healthz)
	http.HandleFunc("/hello", hello)
	http.HandleFunc("/", ServeHTTP)
	http.Handle("/metrics", promhttp.Handler())
	s := &http.Server{
		Addr:    ":80",
		Handler: nil,
	}
	go func() {
		if err := s.ListenAndServe(); err != nil {
			log.Printf("Listen: %s\n", err)
		}
	}()
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	log.Println("Shutdown Server1...")
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()
	if err := s.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown: ", err)
	}
	log.Println("Server exited")
}

// RemoteIp 返回远程客户端的 IP，如 192.168.1.1
func RemoteIp(req *http.Request) string {
	remoteAddr := req.RemoteAddr
	if ip := exnet.ClientPublicIP(req); ip != "" {
		remoteAddr = ip
	} else if ip := exnet.ClientIP(req); ip != "" {
		remoteAddr = ip
	} else if ip := req.Header.Get("X-Real-IP"); ip != "" {
		remoteAddr = ip
	} else if ip = req.Header.Get("X-Forwarded-For"); ip != "" {
		remoteAddr = ip
	} else {
		remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
	}
	if remoteAddr == "::1" {
		remoteAddr = "127.0.0.1"
	}

	return remoteAddr
}
